
package com.scs.application.modules.settlement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.base.request.HospitalMaterialRequest;
import com.scs.application.modules.base.service.HospitalMaterialService;
import com.scs.application.modules.base.vo.HospitalMaterialVO;
import com.scs.application.modules.settlement.dto.StockSnapshotDTO;
import com.scs.application.modules.settlement.entity.StockSnapshot;
import com.scs.application.modules.settlement.mapper.StockSnapshotMapper;
import com.scs.application.modules.settlement.request.StockSnapshotQueryRequest;
import com.scs.application.modules.settlement.service.StockSnapshotService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 库存快照 service 实现
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class StockSnapshotServiceImpl extends BaseServiceImpl<StockSnapshotMapper, StockSnapshot> implements StockSnapshotService {


    @Autowired
    private HospitalMaterialService hospitalMaterialService;

    @Override
    public List<StockSnapshot> list(StockSnapshotQueryRequest request) {
        List<StockSnapshot> list = this.list(getQueryWrapper(request));
        return list;
    }

    @Override
    public IPage<StockSnapshot> page(StockSnapshotQueryRequest request) {
        IPage page = this.page(request.getPage(), getQueryWrapper(request));
        return page;
    }

    @Override
    public void savePeriodStock(StockSnapshotDTO dto) {
        String periodNo = dto.getPeriodNo();

        if (dto.isDeleteExisting()) {
            this.remove(new QueryWrapper<StockSnapshot>().eq("period_no", periodNo));
        } else {
            int count = this.count(new QueryWrapper<StockSnapshot>().eq("period_no", periodNo));
            if (count != 0) {
                throw new BusinessException(String.format("期号%s 库存已经快照过了，不支持重复快照", periodNo));
            }
        }

        // 获取所有耗材
        List<HospitalMaterialVO> hms = hospitalMaterialService.listVO(new HospitalMaterialRequest());

        String hospitalName = UserUtils.getHospital().getName();
        long emptyCodeCount = hms.stream().filter(o -> StringUtils.isBlank(o.getMaterialCode())).count();
        if (emptyCodeCount > 0) {
            log.warn("当前医院 {} 下有 {} 个耗材未维护耗材编码，请注意", hospitalName, emptyCodeCount);
        }

        // 以耗材编码作为key
        Map<String, HospitalMaterialVO> map = hms.stream().filter(o -> StringUtils.isNotBlank(o.getMaterialCode()))
                .collect(Collectors.toMap(o -> o.getMaterialCode(), o -> o, (o1, o2) -> o1));
        List<StockSnapshotDTO.StockItem> items = dto.getItems();

        List<StockSnapshot> snapshots = Lists.newArrayList();

        for (StockSnapshotDTO.StockItem item : items) {

            HospitalMaterialVO vo = map.get(item.getMaterialCode());
            if (vo == null) {
                log.warn("耗材编码 {} 在MSCM系统中不存在，请注意", item.getMaterialCode());
                continue;
            }
            StockSnapshot snapshot = new StockSnapshot();

            snapshot.setHospitalId(UserUtils.getHospitalId())
                    .setHospitalName(hospitalName)
                    .setSupplierId(vo.getSupplierId())
                    .setSupplierName(vo.getSupplierName())
                    .setMaterialId(vo.getMaterialId())
                    .setMaterialSpecId(vo.getMaterialSpecId())
                    .setMaterialCode(vo.getMaterialCode())
                    .setMaterialName(vo.getMaterialName())
                    .setMaterialSpec(vo.getMaterialSpec())
                    .setPrice(vo.getPrice())
                    .setUnit(vo.getUnit())
                    .setPeriodNo(periodNo)
                    .setQty(item.getQty())
                    .setManufacturerId(vo.getManufacturerId())
                    .setManufacturerName(vo.getManufacturerName())
                    .setHospitalMaterialId(vo.getId());// 添加耗材主键id;
            snapshots.add(snapshot);
        }
        if (!snapshots.isEmpty()) {
            this.saveBatch(snapshots);
        }

    }

    private QueryWrapper<StockSnapshot> getQueryWrapper(StockSnapshotQueryRequest request) {
        QueryWrapper<StockSnapshot> wrapper = Wrappers.<StockSnapshot>query()
                .eq(StringUtils.isNotBlank(request.getPeriodNo()), "period_no", request.getPeriodNo())
                .eq(StringUtils.isNotBlank(request.getMaterialName()), "material_name", request.getMaterialName())
                .eq(StringUtils.isNotBlank(request.getMaterialSpec()), "material_spec", request.getMaterialSpec())
                .like(StringUtils.isNotBlank(request.getManufacturerName()), "manufacturer_name", request.getManufacturerName())
                .gt("qty", 0)
                .orderByDesc("gmt_modified");

        if (UserUtils.isSupplier()) {
//            wrapper.eq("supplier_id", UserUtils.getSupplierId());
            wrapper.and(w ->{
                return w.eq("supplier_id", UserUtils.getSupplierId()).or()
                        .exists(" select 1 from supplier_distribution w1  inner join supplier_distribution_item w2 on w2.supplier_distribution_id = w1.id where w1.authorize_id = '"+UserUtils.getSupplierId()+"' and w2.hospital_material_id = stock_snapshot.hospital_material_id ");
            });
        }
        if (UserUtils.isHospital()) {
            wrapper.eq("hospital_id", UserUtils.getHospitalId());
        }
        return wrapper;
    }
}
